package de.muyat.kablosuzizci.istemci;

import tr.muyat.kablosuzizci.istemci.yardimcilarmodulu.FormatHatasi;
import tr.muyat.kablosuzizci.istemci.yardimcilarmodulu.Kullanislilar;

/**
 * azimuth, pitch, roll aci uclusunden olusan oryantasyon vektorunu temsil eder.
 *
 * @author Dzhoshkun Ismail Shakir
 *
 */
public class Oryantasyon {
	private float azimuth, pitch, roll;
	
	/**
	 * Bu sinifin her objesi bu kadar byte olarak serilestirilir.
	 */
	public static final int DIZIN_BYTE_UZUNLUGU = 3 * 4;
	
	@SuppressWarnings("unused")
	private Oryantasyon() {
		
	}
	
	/**
	 * 
	 * @param azimuth
	 * @param pitch
	 * @param roll
	 * @throws IllegalArgumentException verilen aci degerleri 0-2pi arasinda degilse
	 */
	public Oryantasyon(float azimuth, float pitch, float roll) throws IllegalArgumentException {
		if (!Kullanislilar.aciDegeriDogruMu(azimuth))
			throw new IllegalArgumentException();
		if (!Kullanislilar.aciDegeriDogruMu(pitch))
			throw new IllegalArgumentException();
		if (!Kullanislilar.aciDegeriDogruMu(roll))
			throw new IllegalArgumentException();

		this.azimuth = azimuth;
		this.pitch = pitch;
		this.roll = roll;
	}
	
	/**
	 * @return the azimuth
	 */
	public float getAzimuth() {
		return azimuth;
	}
	
	/**
	 * @return the pitch
	 */
	public float getPitch() {
		return pitch;
	}
	
	/**
	 * @return the roll
	 */
	public float getRoll() {
		return roll;
	}

	/**
	 * 
	 * @return oryantasyon bilgilerinin byte dizini olarak serilestirilmis hali
	 */
	public byte[] serilestir() {
		byte[] serilestirilmisOryantasyon = new byte[DIZIN_BYTE_UZUNLUGU];
		byte[] azimuth = Kullanislilar.byteDizinineDonustur(this.azimuth);
		System.arraycopy(azimuth, 0, serilestirilmisOryantasyon, 0, 4);
		byte[] pitch = Kullanislilar.byteDizinineDonustur(this.pitch);
		System.arraycopy(pitch, 0, serilestirilmisOryantasyon, 4, 4);
		byte[] roll = Kullanislilar.byteDizinineDonustur(this.roll);
		System.arraycopy(roll, 0, serilestirilmisOryantasyon, 8, 4);
		
		return serilestirilmisOryantasyon;
	}
	
	/**
	 * 
	 * @param serilestirilmisOryantasyon
	 * @param offset verilen dizinin neresinden baslayayim okumaya?
	 * @return parametre olarak girilen byte dizininden elde edilen obje
	 * @throws FormatHatasi
	 */
	public static Oryantasyon seridenOku(byte[] serilestirilmisOryantasyon, int offset) throws FormatHatasi {
		try {
			float[] matris = new float[3];
			for (int i=0; i<3; i++) {
				byte[] deger = new byte[4];
				System.arraycopy(serilestirilmisOryantasyon, offset+4*i, deger, 0, 4);
				matris[i] = Kullanislilar.floataDonustur(deger);
			}
			return new Oryantasyon(matris[0], matris[1], matris[2]);
		}
		catch (ArrayIndexOutOfBoundsException e) {
			throw new FormatHatasi();
		}
	}
	
	/**
	 * Bu nesnenin butun degerleri {@code baska} bir nesneden kopyalanir. Surekli yeni
	 * nesne yaratmamak icin boyle bir hack gerekti.
	 * @param baska
	 */
	public void kopyala(Oryantasyon baska) {
		this.azimuth = baska.azimuth;
		this.pitch = baska.pitch;
		this.roll = baska.roll;
	}
}